home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 1
/
Nebula One.iso
/
Mail
/
MailEnclosure
/
Source.v0.15
/
FileShelfView.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
8KB
|
338 lines
#import "FileShelfView.h"
#import "FileCollection.h"
#import "TokenString.h"
#import "FileName.h"
static id font;
@interface FileShelfView (PRIVATE)
- _burstNames;
- (const char *) _formatFileName: str width: (float)len;
- (NXPoint *) _pointForIndex: (int) index;
- (int) _indexForPoint: (NXPoint *)hit;
@end
@implementation FileShelfView
-initFrame:(const NXRect *)rect
{
[super initFrame: rect];
[self registerForDraggedTypes:&NXFilenamePboardType count:1];
images = [[List alloc] init];
fileNames = [[List alloc] init];
singleNames = [[FileCollection alloc] init];
nameListDirty = NO;
font = [Font systemFontOfSize: 0 matrix: NX_IDENTITYMATRIX];
[self setEnabled: YES];
[self setTitleWidth: 60];
[self setShowNames: YES];
return self;
}
- free
{
[self unregisterDraggedTypes];
[images freeObjects];
[images free];
[fileNames freeObjects];
[fileNames free];
[singleNames freeObjects];
[singleNames free];
return [super free];
}
- empty
{
[images freeObjects];
[fileNames freeObjects];
[self display];
return self;
}
- drawSelf:(NXRect *)r :(int) count
{
NXPoint *point;
int cnt, y;
const char *label;
/* Erase the whole view */
if(enabled)
NXDrawGrayBezel(&bounds, &bounds); /* with bezel if enabled */
else
{
NXSetColor ([window backgroundColor]);
NXRectFill (&bounds);
return self;
}
PSsetgray(NX_BLACK);
[font set];
for(y = 0, cnt = [images count]; y < cnt; y++)
{
[[images objectAt: y] composite: NX_SOVER toPoint: point = [self _pointForIndex: y]];
if(showNames)
{
label = [self _formatFileName: [fileNames objectAt: y] width: titleWidth - 4.0 ];
PSmoveto((point->x + 24.0) - ([font getWidthOf: label]/2.0) , point->y - [font pointSize]);
PSshow(label);
}
}
return self;
}
- fileNames
{
if(nameListDirty) /* if the list has changed we need to burst it before accessing */
[self _burstNames];
return singleNames;
}
- setEnabled: (BOOL)flag /* will it accept files? */
{
if(flag == enabled)
return self;
enabled = flag;
[self empty];
[self display];
return self;
}
- (BOOL) enabled
{
return enabled;
}
- addFile: (const char *)filename /* add file(s) manually */
{
id file = [[StringStorage alloc] init: filename];
NXImage *image;
image = [[Application workspace] getIconForFile: [file stringValue]];
if(!(image && enabled))
{
[file free];
return nil;
}
[images addObject: image];
[fileNames addObject: file];
[self display];
nameListDirty = YES;
return self;
}
- mouseDown: (NXEvent *)anEvent
{
NXEvent saveEvent;
NXPoint offset, origin;
Pasteboard *dragPasteboard;
offset.x = offset.y = 0;
saveEvent = *anEvent;
/* find the hit icon and its origin */
origin = anEvent->location;
[self convertPoint: &origin fromView: nil];
dragIndex = [self _indexForPoint: &origin];
/* create and load pasteboard - then start drag */
dragPasteboard = [Pasteboard newName: NXDragPboard];
[dragPasteboard declareTypes: &NXFilenamePboardType num:1 owner:self];
[dragPasteboard writeType: NXFilenamePboardType data: [[fileNames objectAt: dragIndex] stringValue]
length: [[fileNames objectAt: dragIndex] strlen]];
[self dragImage: [images objectAt: dragIndex] at: [self _pointForIndex: dragIndex] offset: &offset
event: &saveEvent pasteboard: dragPasteboard source: self slideBack: NO];
return [super mouseDown: anEvent];
}
- setShowNames: (BOOL) flag /* Should the names appear on the shelf? */
{
showNames = flag;
return self;
}
-(BOOL) showNames
{
return showNames;
}
- setTitleWidth: (float) aWidth /* how wide is a shelf slot - min 50 */
{
titleWidth = (aWidth > 50.0 ? aWidth : 50.0);
return self;
}
- (float) titleWidth
{
return titleWidth;
}
@end
@implementation FileShelfView (NXDraggingDestinationProtocol)
- (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
{
if(enabled && ([sender draggingSourceOperationMask] & NX_DragOperationCopy))
return NX_DragOperationCopy;
else
return NX_DragOperationNone;
}
- draggingExited:(id <NXDraggingInfo>) sender
{
return self;
}
- (BOOL)prepareForDragOperation:(id <NXDraggingInfo>)sender
{
return YES;
}
- (BOOL)performDragOperation:(id <NXDraggingInfo>)sender
{
return ([self draggingEntered: sender] == NX_DragOperationNone) ? NO : YES;
}
- concludeDragOperation:(id <NXDraggingInfo>)sender
{
Pasteboard *pboard = [sender draggingPasteboard];
char *files;
int len;
id aFile;
[pboard readType:NXFilenamePboardType data: &files length: &len];
if(len)
{
[images addObject: [sender draggedImageCopy]];
aFile = [[StringStorage alloc] init: files];
[fileNames addObject:aFile];
[self display];
nameListDirty = YES;
}
return self;
}
@end
@implementation FileShelfView (FSVNXDraggingSource)
- (NXDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
{
return NX_DragOperationCopy;
}
- draggedImage:(NXImage *)image endedAt:(NXPoint *)screenPoint deposited:(BOOL)didDeposit
{
if(!didDeposit)
{
[[images removeObjectAt: dragIndex] free];
[[fileNames removeObjectAt: dragIndex] free];
[self display];
nameListDirty = YES;
}
return self;
}
- (BOOL)ignoreModifierKeysWhileDragging
{
return NO;
}
@end
@implementation FileShelfView (PRIVATE)
/*
* fileNames may contain multiple file entries - break them out to single entries.
*/
- _burstNames
{
int x, cnt;
id someNames = [[TokenString alloc] init];
id aFileName;
const char *fileNameStr;
[singleNames freeObjects]; /* free old version of the list */
[someNames setSeparator: '\t'];
for(x = 0, cnt = [fileNames count]; x < cnt; x++)
{
[someNames setStringValue: [[fileNames objectAt: x] stringValue]];
while(fileNameStr = [someNames popStringValue])
{
aFileName = [[StringStorage alloc] init: fileNameStr];
[singleNames addObject: aFileName];
}
}
[someNames free];
nameListDirty = NO;
return self;
}
- (const char *) _formatFileName: fn width: (float)len
{ /* format file names like the Workspace shelf. Handle multiple items */
static char buf[MAXPATHLEN];
const char *str = [fn stringValue];
int x, cnt;
for(cnt = 0, x = 0; str[x]; x++)
{
if(str[x] == '\t')
cnt++;
}
if(cnt)
sprintf(buf,"%d items", cnt + 1);
else
strcpy(buf,[fn basename]);
if([font getWidthOf: buf] > len)
{
for(x = strlen(str); x > 0 ; x--)
{
if([font getWidthOf: buf] <= len)
break;
buf[x - 1] = (char)0;
}
strcpy(buf + (x - 3), "...");
}
return buf;
}
- (NXPoint *) _pointForIndex: (int) index /* calculate the corner point for the nth icon */
{
static NXPoint point;
int row, perRow;
perRow = NX_WIDTH(&bounds)/titleWidth;
row = (index/perRow) + 1;
point.x = (float)((index % perRow) * titleWidth) + ((titleWidth/2.0) - 24.0);
point.y = NX_HEIGHT(&bounds) - (row * 52);
if(showNames)
point.y -= ((row - 1) * [font pointSize]);
return &point;
}
- (int) _indexForPoint: (NXPoint *)hit /* based on a point which icon was hit? */
{
int column, row;
row = (NX_HEIGHT(&bounds) - hit->y)/(52 + (showNames ? [font pointSize] : 0));
column = hit->x/titleWidth;
return column + (row * (int)(NX_WIDTH(&bounds)/titleWidth));
}
@end